home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (C) 1994, Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
- * the contents of this file may not be disclosed to third parties, copied or
- * duplicated in any form, in whole or in part, without the prior written
- * permission of Silicon Graphics, Inc.
- *
- * RESTRICTED RIGHTS LEGEND:
- * Use, duplication or disclosure by the Government is subject to restrictions
- * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
- * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
- * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
- * rights reserved under the Copyright Laws of the United States.
- */
- /*_______________________________________________________________________
- |
- | blixsound.c - handles all the sound effects for blix.
- |
- | it is partialy a copy of bzsound written by Chris Fouts.
- | There was no need to re-invent it. This is quite a piece of good
- | software. Thanks Chris.
- |
- |
- | Modified to read different data from a different place
- | and to allow for a continous tune to be played
- | also fixed a bug on indigo^2, and added support for
- | volume change in audio control panel.
- | Also removed the complicated explosion sound handling. There are now
- | only three pan position for the sound (-1, 0, 1) (= left, middle, right)
- | which saves quite some memory (left and right share the storage), and
- | only one depth. The sound for the lift also pans.
- |
- | Frans van Hoesel - Xtreme Graphics Software.
- | January, 1994
- */
-
-
-
-
-
-
- /*________________________________________________________________________
- |
- | BZ - Multiplayer tank game - Sound support.
- |
- | Chris Fouts - Silicon Graphics, Inc.
- | October, 1991
- |________________________________________________________________________
- |
- | Copyright (c) 1990 SGI All Rights Reserved
- | THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF SGI
- | The copyright notice above does not evidence any
- | actual or intended publication of such source code,
- | and is an unpublished work by Silicon Graphics, Inc.
- | This material contains CONFIDENTIAL INFORMATION that
- | is the property of Silicon Graphics, Inc. Any use,
- | duplication or disclosure not specifically authorized
- | by Silicon Graphics is strictly prohibited.
- |
- | RESTRICTED RIGHTS LEGEND:
- | Use, duplication or disclosure by the
- | Government is subject to restrictions
- | as set forth in subdivision (c)(1)(ii) of
- | the Rights in Technical Data and Computer
- | Software clause at DFARS 52.227-7013,
- | and/or in similar or successor clauses in the FAR,
- | DOD or NASA FAR Supplement. Unpublished- rights
- | reserved under the Copyright Laws of the United States.
- | Contractor is SILICON GRAPHICS, INC., 2011 N. Shoreline
- | Blvd., Mountain View, CA 94039-7311
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <fcntl.h>
- #include <errno.h>
- #include <sys/types.h>
- #include <sys/prctl.h>
- #include <string.h>
- #include <signal.h>
- #include <malloc.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <audio.h>
- #include <invent.h>
- #include <gl/gl.h>
-
- #include "aiff.h"
- #include "blixsound.h"
- #include "blix.h"
-
- int pause( void ) ;
-
- /* as the timeslice is 0.3 seconds it seems appropiate to make this
- * TIMECHUNK variable at least 0.3 seconds. 0.1 seems to work great though
- * A time of 0.3 seconds makes it possible that the requested sound is
- * delayed by that much.
- */
- #define TIMECHUNK 0.1 /* duration of buffer data */
- /*
- * we're going to nail down the value of infinity for the IEEE conversion
- * routine below: math.h yields to local definition of HUGE_VAL
- */
- union {
- unsigned long n[2]; /* initialized in main */
- double d;
- } _inf_union;
- #define HUGE_VAL _inf_union.d;
- #include <math.h>
-
- typedef union {
- unsigned char b[2];
- short s;
- } align_short_t;
-
- typedef union {
- unsigned char b[4];
- long l;
- } align_long_t;
-
-
- #define MAX_AUDIO_PORTS 3
-
- static unsigned long orig_left_gain ;
- static unsigned long orig_right_gain ;
- static unsigned long orig_output_rate ;
- static unsigned long curr_left_gain ;
- static unsigned long curr_right_gain ;
- static long sound_size[SFX_N_SOUNDS] ;
- static long sound_repeat[SFX_N_SOUNDS] ;
- static short *sound_data[SFX_N_SOUNDS] ;
- static char *sound_file[SFX_N_SOUNDS] = {
- "snd/welcome.aiff",
- "snd/beep.aiff",
- "snd/explosion.aiff",
- "snd/explosion.aiff", /* extra for panned sound */
- "snd/lift.aiff",
- "snd/lift.aiff", /* same for lift sound */
- "snd/tune_a.aiff",
- "snd/tune_b.aiff",
- "snd/tune_c.aiff",
- "snd/donk_c.aiff",
- "snd/planet.aiff",
- "snd/pop.aiff", /* yes, for pop-up menu */
- "snd/goodbye.aiff"
- } ;
- static short *new_sound_data ;
- static long new_sound_size ;
- static long new_sound_repeat;
- static int new_sound = 0 ;
- static char *filename; /* input file name */
- static int bytes_per_samp; /* sample width */
- static int samps_per_frame; /* frame size */
- static int frames_per_sec; /* sample rate */
- static ALport audio_port[MAX_AUDIO_PORTS+1] ;/* foreground audio ports */
- static int sound_child = 0 ;
- static int sound_enabled = 0 ;
- static int has_sound_hw = 0 ;
- static int tune_enabled = 0;
-
- static unsigned long gain_settings[] =
- { 0, 2, 3, 5, 9, 16, 29, 50, 91, 156, 255 } ;
- static int gain_index ;
-
-
- static int check_for_audio_hw( void ) ;
- static double ConvertFromIeeeExtended( char *bytes ) ;
- static char *init_audio( int fd, audio_params_t *audio_params,
- ssnd_chunk_t *ssnd_data, comm_chunk_t *comm_data,
- long *size ) ;
- static ALport init_audio_port( int all ) ;
- static void init_pan_data(int sound) ;
- static char *load_aiff_file( char *dir, char *name, long *size ) ;
- static char *read_aiff_file( int fd, long *size ) ;
- static int read_chunk_header( int fd, chunk_header_t *chunk_header ) ;
- static void read_comm_chunk( int fd, comm_chunk_t *comm_data,
- audio_params_t *audio_params ) ;
- static void read_form_chunk( int fd, chunk_header_t *chunk_header ) ;
- static void read_ssnd_chunk( int fd, chunk_header_t *chunk_header,
- ssnd_chunk_t *ssnd_data ) ;
- static void reset_audio_hw( void ) ;
- static void set_gain( float l, float r ) ;
- static void set_rate(void);
- static void set_gain_index( unsigned long gain ) ;
- static void signal_sound( short *data, long size , long repeat) ;
- static void skip_chunk( int fd, chunk_header_t *chunk_header ) ;
- static void sound_handler( void *arg ) ;
- static void wake_up( int sig, int code, struct sigcontext *sc ) ;
-
-
- int init_sound( void ) {
- int i ;
- char fullpath[512];
- FILE *f;
-
- if( ( has_sound_hw = check_for_audio_hw() ) != 0 ) {
- if( ( audio_port[0] = init_audio_port( 1 ) ) == NULL ) {
- fprintf( stderr, "%s: no audio ports available\n", basename ) ;
- return( 1 ) ;
- }
-
- if( ( audio_port[1] = init_audio_port( 0 ) ) != NULL ) {
- audio_port[2] = init_audio_port( 0 ) ;
- }
- audio_port[3] = NULL ;
-
-
- strcpy(fullpath, datadir);
- strcat(fullpath, sound_file[0]);
- f = fopen(fullpath, "r");
- if (f == NULL) {
- fprintf(stderr, "%s: cannot locate audio data\n",
- basename);
- gexit();
- exit(1);
- } else {
- fclose(f);
- }
-
- for( i = 0 ; i < SFX_N_SOUNDS ; i++ ) {
- sound_data[i] = (short *)load_aiff_file( datadir,
- sound_file[i], &sound_size[i] ) ;
- sound_repeat[i] = 0;
- }
-
- if( sound_data[SFX_EXPLOSION_L] ) {
- init_pan_data(SFX_EXPLOSION_L) ;
- }
- if (sound_data[SFX_LIFT_L] ) {
- init_pan_data(SFX_LIFT_L) ;
- }
- if (sound_data[SFX_TUNE_A]) {
- sound_repeat[SFX_TUNE_A] = sound_size[SFX_TUNE_A];
- }
- if (sound_data[SFX_TUNE_B]) {
- sound_repeat[SFX_TUNE_B] = sound_size[SFX_TUNE_B];
- }
- if (sound_data[SFX_TUNE_C]) {
- sound_repeat[SFX_TUNE_C] = sound_size[SFX_TUNE_C];
- }
- if( ( sound_child = sproc( sound_handler, PR_SALL, audio_port ) ) < 0 ){
- fprintf( stderr, "%s: could not sproc sound handler: %s\n",
- basename, strerror( errno ) ) ;
- return( 1 ) ;
- } else {
- sound_enabled = 1 ;
- }
- } else {
- sound_enabled = 0 ;
- return( 1 ) ;
- }
-
-
- return( 0 ) ;
- }
-
-
-
- void set_volume(int level) {
- if( level >= 0 &&
- level < sizeof( gain_settings ) / sizeof( gain_settings[0] ) ) {
- gain_index = level ;
- curr_left_gain = curr_right_gain = gain_settings[gain_index] ;
- }
- }
-
-
-
- int toggle_sound( void ) {
- if( has_sound_hw && sound_child )
- sound_enabled = !sound_enabled ;
-
- return( sound_enabled ) ;
- }
-
-
- int toggle_tune( void ) {
- if( has_sound_hw && sound_child )
- tune_enabled = !tune_enabled ;
-
- return( tune_enabled ) ;
- }
-
- void tune_off(void) {
- tune_enabled = 0;
- }
-
-
- void end_sound( void ) {
- if( sound_child > 0 ) {
- kill( sound_child, SIGKILL ) ;
- }
- if( has_sound_hw )
- reset_audio_hw() ;
- }
-
-
- /* ARGSUSED */
- static void wake_up(int sig, int code, struct sigcontext *sc) {
- signal( SIGUSR1, wake_up ) ;
- }
-
-
-
- static void reset_audio_hw( void ) {
- long pvbuf[6] ;
- long buflen ;
-
- pvbuf[0] = AL_LEFT_SPEAKER_GAIN ;
- pvbuf[1] = orig_left_gain ;
- pvbuf[2] = AL_RIGHT_SPEAKER_GAIN ;
- pvbuf[3] = orig_right_gain ;
- pvbuf[4] = AL_OUTPUT_RATE ;
- pvbuf[5] = orig_output_rate ;
- buflen = 6 ;
-
- ALsetparams( AL_DEFAULT_DEVICE, pvbuf, buflen ) ;
- }
-
-
-
- static void set_gain(float l, float r) {
- long pvbuf[6] ;
- long buflen ;
-
- pvbuf[0] = AL_LEFT_SPEAKER_GAIN ;
- pvbuf[1] = l * curr_left_gain ;
- pvbuf[2] = AL_RIGHT_SPEAKER_GAIN ;
- pvbuf[3] = r * curr_right_gain ;
- pvbuf[4] = AL_OUTPUT_RATE ;
- pvbuf[5] = AL_RATE_16000 ;
- buflen = 6 ;
- ALsetparams( AL_DEFAULT_DEVICE, pvbuf, buflen ) ;
- }
-
- static void set_rate(void) {
- long pvbuf[2] ;
- long buflen ;
-
- pvbuf[0] = AL_OUTPUT_RATE ;
- pvbuf[1] = AL_RATE_16000 ;
- buflen = 2 ;
- ALsetparams( AL_DEFAULT_DEVICE, pvbuf, buflen ) ;
- }
-
-
- static void sound_handler(void *arg) {
- ALport *ap = (ALport *)arg ;
- int i ;
- int empty ;
- int next_port = 0 ;
- int n_audio_ports ;
- long max_samps_per_frame ;
- long samps_to_play[MAX_AUDIO_PORTS] ;
- long samps_played[MAX_AUDIO_PORTS] ;
- long samps_repeat[MAX_AUDIO_PORTS] ;
- short *sample[MAX_AUDIO_PORTS] ;
-
- max_samps_per_frame = TIMECHUNK * 16000. ;
- prctl(PR_TERMCHILD);
- n_audio_ports = 0 ;
- while( ap[n_audio_ports] != NULL ) {
- sample[n_audio_ports] = 0 ;
- samps_to_play[n_audio_ports] = 0 ;
- samps_repeat[n_audio_ports] = 0;
- n_audio_ports++ ;
- }
-
- signal( SIGUSR1, wake_up ) ;
-
- while( 1 ) {
- if( new_sound ) {
- sample[next_port] = new_sound_data ;
- samps_to_play[next_port] = new_sound_size ;
- samps_repeat[next_port] = new_sound_repeat;
- samps_played[next_port] = 0 ;
- new_sound = 0 ;
- next_port = ( next_port + 1 ) % n_audio_ports ;
- if (samps_repeat[next_port] != 0) {
- next_port = ( next_port + 1 ) % n_audio_ports ;
- }
- }
- empty = 1 ;
- for( i = 0 ; i < n_audio_ports ; i++ ) {
- if( samps_to_play[i] > 0 ) {
- if( samps_to_play[i] > max_samps_per_frame ) {
- if (samps_repeat[i] != 0) {
- if (!(tune_enabled && sound_enabled)) {
- /* switch off tune */
- samps_to_play[i] = 0;
- samps_repeat[i] = 0;
- continue;
- }
- }
- set_rate();
- ALwritesamps( ap[i], sample[i] + samps_played[i],
- max_samps_per_frame ) ;
- samps_played[i] += max_samps_per_frame ;
- samps_to_play[i] -= max_samps_per_frame ;
- empty = 0 ;
- } else {
- set_rate();
- ALwritesamps( ap[i], sample[i] + samps_played[i],
- samps_to_play[i] ) ;
- if (samps_repeat[i] != 0 && tune_enabled && sound_enabled) {
- samps_to_play[i] = samps_repeat[i];
- samps_played[i] = 0;
- empty = 0;
- } else {
- samps_to_play[i] = 0 ;
- samps_repeat[i] = 0;
- }
- }
- }
- }
- if (empty)
- pause();
- }
- }
-
-
-
- void sfx(int sound) {
- if ((sound != SFX_TUNE_A && sound != SFX_TUNE_B &&
- sound != SFX_TUNE_C) || tune_enabled == 1 ) {
- if( audio_port[0] && sound_data[sound] && sound_enabled ) {
- signal_sound( sound_data[sound], sound_size[sound],
- sound_repeat[sound] ) ;
- }
- }
- }
-
-
- /*_________________________________________________________________________
- |
- | sfx_pan - produce noise at panned position
- |
- | This uses a clever trick, to use the data, one word shifted as the
- | left/right difference. This works, because for stereo, the left and
- | right samples are stored alternatly.
- | However, for the sound in the middle, you need a separate data stream
- | That is the reason why the explosion and lift sound are loaded twice
- | above (which was just my laziness of programming).
- |
- */
-
- void sfx_pan(int sound, int pan) {
- int offset;
-
- if( sound_data[sound] && sound_enabled ) {
- switch (pan) {
- case -1:
- offset = 0;
- sound++;
- break;
- case 1:
- offset = 1;
- sound++;
- default:
- offset = 0;
- break;
- }
- signal_sound( sound_data[sound] + offset, sound_size[sound] - offset*2,0) ;
- }
- }
-
-
- static void signal_sound(short *data, long size, long repeat ) {
- if( sound_child ) {
- new_sound_data = data ;
- new_sound_size = size ;
- new_sound_repeat = repeat;
- new_sound = 1 ;
- kill( sound_child, SIGUSR1 ) ;
- }
- }
-
- static void get_gain(void) {
- long pvbuf[6] ;
- long buflen ;
- pvbuf[0] = AL_LEFT_SPEAKER_GAIN ;
- pvbuf[2] = AL_RIGHT_SPEAKER_GAIN ;
- buflen = 4 ;
- ALgetparams( AL_DEFAULT_DEVICE, pvbuf, buflen ) ;
- curr_left_gain = orig_left_gain = pvbuf[1] ;
- curr_right_gain = orig_right_gain = pvbuf[3] ;
-
- set_gain_index( ( orig_left_gain + orig_right_gain ) / 2 ) ;
-
- }
-
- static ALport init_audio_port(int all) {
- long pvbuf[6] ;
- long buflen ;
- ALconfig audio_port_config;
- ALport ap ;
-
- if( all ) {
- pvbuf[0] = AL_LEFT_SPEAKER_GAIN ;
- pvbuf[2] = AL_RIGHT_SPEAKER_GAIN ;
- pvbuf[4] = AL_OUTPUT_RATE ;
- buflen = 6 ;
- ALgetparams( AL_DEFAULT_DEVICE, pvbuf, buflen ) ;
- curr_left_gain = orig_left_gain = pvbuf[1] ;
- curr_right_gain = orig_right_gain = pvbuf[3] ;
- orig_output_rate = pvbuf[5] ;
-
- set_gain_index( ( orig_left_gain + orig_right_gain ) / 2 ) ;
- }
-
- /*
- * configure and open audio port
- */
- audio_port_config = ALnewconfig();
- ALsetwidth( audio_port_config, AL_SAMPLE_16 ) ;
- ALsetchannels( audio_port_config, AL_STEREO ) ;
-
- /*
- * make the ring buffer large enough to hold TIMECHUNK sec of audio samples
- */
- ALsetqueuesize( audio_port_config, 16000 * TIMECHUNK ) ;
- ap = ALopenport( basename, "w", audio_port_config ) ;
-
- ALfreeconfig( audio_port_config ) ;
-
- return( ap ) ;
- }
-
-
-
- static char *load_aiff_file(char *dir, char *name, long *size) {
- int fd ;
- char *data ;
-
- filename = (char *)malloc( strlen( name ) + strlen( dir ) + 3 ) ;
- sprintf( filename, "%s/%s", dir, name ) ;
-
- if( ( fd = open( filename, O_RDONLY ) ) < 0 ) {
- fprintf( stderr, "%s: can't open %s: %s\n", basename, filename,
- strerror( errno ) ) ;
- free( filename ) ;
- return( NULL ) ;
- }
-
- data = read_aiff_file( fd, size ) ;
-
- free( filename ) ;
-
- close( fd ) ;
-
- return( data ) ;
- }
-
-
-
- static char *read_aiff_file(int fd, long *size ) {
- int n ;
- chunk_header_t chunk_header ;
- comm_chunk_t comm_data ;
- ssnd_chunk_t ssnd_data ;
- audio_params_t audio_params ;
-
- if( ( n = read_chunk_header( fd, &chunk_header ) ) != CHUNK_HEADER ) {
- fprintf( stderr, "%s: failed to read FORM chunk header\n", basename ) ;
- return( NULL ) ;
- }
-
- if( strncmp( chunk_header.id, "FORM", 4 ) ) {
- fprintf( stderr, "%s: couldn't find FORM chunk id\n", basename ) ;
- return( NULL ) ;
- }
-
- read_form_chunk( fd, &chunk_header ) ;
-
- /*
- * loop on the local chunks
- */
- while( ( n = read_chunk_header( fd, &chunk_header ) ) != 0 ) {
- if( n != CHUNK_HEADER ) {
- fprintf( stderr, "%s: failed to read a chunk header\n", basename ) ;
- return( NULL ) ;
- }
-
- /* common */
- if( !strncmp( chunk_header.id, "COMM", 4 ) ) {
- read_comm_chunk( fd, &comm_data, &audio_params ) ;
- }
- /* sound data */
- else if( !strncmp( chunk_header.id, "SSND", 4 ) ) {
- read_ssnd_chunk( fd, &chunk_header, &ssnd_data ) ;
- }
- else if( ( !strncmp( chunk_header.id, "MARK", 4 ) ) /* marker */
- || ( !strncmp( chunk_header.id, "INST", 4 ) ) /* instrument */
- || ( !strncmp( chunk_header.id, "APPL", 4 ) ) /* appl specific */
- || ( !strncmp( chunk_header.id, "MIDI", 4 ) ) /* midi data */
- || ( !strncmp( chunk_header.id, "AESD", 4 ) ) /* audio rec */
- || ( !strncmp( chunk_header.id, "COMT", 4 ) ) /* comments */
- || ( !strncmp( chunk_header.id, "NAME", 4 ) ) /* text */
- || ( !strncmp( chunk_header.id, "AUTH", 4 ) ) /* text */
- || ( !strncmp( chunk_header.id, "(c) ", 4 ) ) /* text */
- || ( !strncmp( chunk_header.id, "ANNO", 4 ) ) /* text */
- ) {
- skip_chunk( fd, &chunk_header ) ;
- }
- else {
- fprintf( stderr, "%s: bad chunk id 0x%02x%02x%02x%02x\n",
- basename, chunk_header.id[0],chunk_header.id[1],
- chunk_header.id[2], chunk_header.id[3]);
- }
- } /* while */
-
- return( init_audio( fd, &audio_params, &ssnd_data, &comm_data, size ) ) ;
- }
-
-
-
- /*
- * R E A D _ C H U N K _ H E A D E R
- */
- static int read_chunk_header(int fd, chunk_header_t *chunk_header ) {
- align_long_t align_long ;
- char buf[CHUNK_HEADER] ;
- int i ;
- int n ;
-
- if( ( n = read( fd, buf, CHUNK_HEADER) ) != CHUNK_HEADER ) {
- return( n ) ;
- }
-
- for( i = 0 ; i < 4 ; i++ ) {
- chunk_header->id[i] = buf[i] ;
- }
-
- for( i = 0 ; i < 4 ; i++ ) {
- align_long.b[i] = buf[i+4] ;
- }
- chunk_header->size = align_long.l ;
-
- return( CHUNK_HEADER ) ;
- }
-
-
-
-
- static void read_form_chunk(int fd, chunk_header_t *chunk_header ) {
- char buf[FORM_CHUNK_DATA];
-
- if( chunk_header->size < 0 ) {
- fprintf( stderr, "%s: invalid FORM chunk data size %ld\n", basename,
- chunk_header->size ) ;
- gexit();
- exit( 1 ) ;
- } else if( chunk_header->size == 0 ) {
- fprintf( stderr, "%s: FORM chunk data size = 0\n", basename ) ;
- gexit();
- exit( 0 ) ;
- }
-
- if( read( fd, buf, FORM_CHUNK_DATA ) != FORM_CHUNK_DATA ) {
- fprintf( stderr, "%s: couldn't read AIFF identifier from %s\n",
- basename, filename ) ;
- gexit();
- exit( 1 ) ;
- }
- if( strncmp( buf, "AIFF", 4 ) ) {
- fprintf( stderr, "%s: %s does not have an AIFF identifier\n",
- basename, filename ) ;
- gexit();
- exit(1);
- }
- }
-
-
-
- /*
- * R E A D _ C O M M _ C H U N K
- */
- static void read_comm_chunk(int fd, comm_chunk_t *comm_data,
- audio_params_t *audio_params) {
- int n;
- char *buf, *bufp;
- int i;
- align_short_t align_short;
- align_long_t align_long;
- double tmpdouble;
-
- buf = (char *) malloc(COMM_CHUNK_DATA + 1); /* leave an extra loc at the end */
-
- if ((n = read(fd, buf, COMM_CHUNK_DATA)) != COMM_CHUNK_DATA)
- {
- fprintf(stderr,
- "%s: failed to read COMM chunk data. Expected %d bytes, got %d.\n",
- basename, COMM_CHUNK_DATA, n);
- gexit();
- exit(1);
- }
- bufp = buf;
- for (i=0; i<2; i++)
- {
- align_short.b[i] = *bufp++;
- }
- comm_data->nchannels = align_short.s;
- for (i=0; i<4; i++)
- {
- align_long.b[i] = *bufp++;
- }
- comm_data->nsampframes = align_long.l;
- for (i=0; i<2; i++)
- {
- align_short.b[i] = *bufp++;
- }
- comm_data->sampwidth = align_short.s;
-
- /*
- * the sample rate value from the common chunk is an 80-bit IEEE extended
- * floating point number:
- * [s bit] [15 exp bits (bias=16383)] [64 mant bits (leading 1 not hidden)]
- *
- */
- tmpdouble = ConvertFromIeeeExtended(bufp);
- bufp+=10;
- comm_data->samprate = (long)tmpdouble;
-
- switch (comm_data->samprate)
- {
- case 48000:
- audio_params->samprate = AL_RATE_48000;
- break;
- case 44100:
- audio_params->samprate = AL_RATE_44100;
- break;
- case 32000:
- audio_params->samprate = AL_RATE_32000;
- break;
- case 22050:
- audio_params->samprate = AL_RATE_22050;
- break;
- case 16000:
- audio_params->samprate = AL_RATE_16000;
- break;
- case 11025:
- audio_params->samprate = AL_RATE_11025;
- break;
- case 8000:
- audio_params->samprate = AL_RATE_8000;
- break;
- default:
- fprintf(stderr,"%s: can't set output sample rate to %ld\n",
- basename, comm_data->samprate);
- audio_params->samprate = AL_RATE_48000;
- }
-
- switch (comm_data->nchannels)
- {
- case 1:
- audio_params->nchannels = AL_MONO;
- break;
- case 2:
- audio_params->nchannels = AL_STEREO;
- break;
- default:
- fprintf(stderr, "%s: can't handle %d channels per frame\n",
- basename, comm_data->nchannels);
- audio_params->nchannels = AL_STEREO;
- }
- switch (comm_data->sampwidth)
- {
- case 8:
- audio_params->sampwidth = AL_SAMPLE_8;
- break;
- case 16:
- audio_params->sampwidth = AL_SAMPLE_16;
- break;
- case 24:
- audio_params->sampwidth = AL_SAMPLE_24;
- break;
- default:
- fprintf(stderr, "%s: unsupported sample width %d bits\n",
- basename, comm_data->nchannels);
- audio_params->sampwidth = AL_SAMPLE_16;
- }
- free(buf);
- }
-
-
-
- static void read_ssnd_chunk(
- int fd,
- chunk_header_t *chunk_header,
- ssnd_chunk_t *ssnd_data
- )
- {
- char buf[SSND_CHUNK_DATA];
- int i;
- align_long_t align_long;
-
- read(fd, buf, SSND_CHUNK_DATA);
-
- for (i=0; i<4; i++)
- {
- align_long.b[i] = buf[i];
- }
- ssnd_data->offset = align_long.l;
- for (i=0; i<4; i++)
- {
- align_long.b[i] = buf[i+4];
- }
- ssnd_data->blocksize = align_long.l;
- /*
- * store the offset to the beginning of the audio sample data so that
- * we can come back and play it later
- */
- ssnd_data->file_position = lseek(fd, 0, SEEK_CUR);
- ssnd_data->sample_area_bytes = chunk_header->size - 2*sizeof(long);
- if (chunk_header->size %2 == 1)
- {
- ssnd_data->sample_area_bytes++;
- }
-
- /*
- * move the fileptr to the end of the chunk
- */
- lseek(fd, ssnd_data->sample_area_bytes, SEEK_CUR);
- }
-
-
-
- /*
- * S K I P _ C H U N K
- */
- static void skip_chunk(
- int fd,
- chunk_header_t *chunk_header
- )
- {
- char id[5];
- int s;
-
- strncpy(id, chunk_header->id, 4);
- id[4] = '\0';
-
- /* skip the pad byte, if necessary */
- s = ((chunk_header->size % 2) == 1) ? chunk_header->size + 1 : chunk_header->size;
- lseek(fd, s, SEEK_CUR);
- }
-
-
-
-
- /*
- * C O N V E R T F R O M I E E E E X T E N D E D
- */
-
- /*
- * Copyright (C) 1988-1991 Apple Computer, Inc.
- * All rights reserved.
- *
- * Warranty Information
- * Even though Apple has reviewed this software, Apple makes no warranty
- * or representation, either express or implied, with respect to this
- * software, its quality, accuracy, merchantability, or fitness for a
- * particular purpose. As a result, this software is provided "as is,"
- * and you, its user, are assuming the entire risk as to its quality
- * and accuracy.
- *
- * This code may be used and freely distributed as long as it includes
- * this copyright notice and the above warranty information.
-
- * Machine-independent I/O routines for IEEE floating-point numbers.
- *
- * NaN's and infinities are converted to HUGE_VAL or HUGE, which
- * happens to be infinity on IEEE machines. Unfortunately, it is
- * impossible to preserve NaN's in a machine-independent way.
- * Infinities are, however, preserved on IEEE machines.
- *
- * These routines have been tested on the following machines:
- * Apple Macintosh, MPW 3.1 C compiler
- * Apple Macintosh, THINK C compiler
- * Silicon Graphics IRIS, MIPS compiler
- * Cray X/MP and Y/MP
- * Digital Equipment VAX
- *
- *
- * Implemented by Malcolm Slaney and Ken Turkowski.
- *
- * Malcolm Slaney contributions during 1988-1990 include big- and little-
- * endian file I/O, conversion to and from Motorola's extended 80-bit
- * floating-point format, and conversions to and from IEEE single-
- * precision floating-point format.
- *
- * In 1991, Ken Turkowski implemented the conversions to and from
- * IEEE double-precision format, added more precision to the extended
- * conversions, and accommodated conversions involving +/- infinity,
- * NaN's, and denormalized numbers.
- */
-
- #ifndef HUGE_VAL
- # define HUGE_VAL HUGE
- #endif /* HUGE_VAL */
-
- # define UnsignedToFloat(u) \
- (((double)((long)(u - 2147483647L - 1))) + 2147483648.0)
-
- /****************************************************************
- * Extended precision IEEE floating-point conversion routine.
- ****************************************************************/
-
- static double ConvertFromIeeeExtended(char *bytes) {
- double f ;
- long expon ;
- unsigned long hiMant ;
- unsigned long loMant ;
-
- expon = ( ( bytes[0] & 0x7F ) << 8 ) | ( bytes[1] & 0xFF ) ;
- hiMant = ( (unsigned long)( bytes[2] & 0xFF ) << 24 )
- | ( (unsigned long)( bytes[3] & 0xFF ) << 16 )
- | ( (unsigned long)( bytes[4] & 0xFF ) << 8 )
- | ( (unsigned long)( bytes[5] & 0xFF ) ) ;
- loMant = ( (unsigned long)( bytes[6] & 0xFF ) << 24 )
- | ( (unsigned long)( bytes[7] & 0xFF ) << 16 )
- | ( (unsigned long)( bytes[8] & 0xFF ) << 8 )
- | ( (unsigned long)( bytes[9] & 0xFF ) ) ;
-
- if( expon == 0 && hiMant == 0 && loMant == 0 ) {
- f = 0;
- } else {
- if( expon == 0x7FFF ) { /* Infinity or NaN */
- f = HUGE_VAL;
- } else {
- expon -= 16383;
- f = ldexp( UnsignedToFloat( hiMant ), expon-=31 ) ;
- f += ldexp( UnsignedToFloat( loMant ), expon-=32 ) ;
- }
- }
-
- if( bytes[0] & 0x80 )
- return( -f ) ;
- else
- return( f ) ;
- }
-
-
-
- /*
- * I N I T _ A U D I O
- */
- static char *init_audio( int fd, audio_params_t *audio_params,
- ssnd_chunk_t *ssnd_data, comm_chunk_t *comm_data,
- long *size) {
-
- char *buf ;
- int bytes_read ;
-
- /*
- * decide what size blocks of samples we should read from the
- * AIFF file and pass to ALwritesamps
- */
- switch( audio_params->sampwidth ) {
- default :
- case AL_SAMPLE_8 :
- fprintf( stderr, "%s: sound file %s is not 16 bytes/sample\n",
- basename, filename ) ;
- return( NULL ) ;
-
- case AL_SAMPLE_16 :
- bytes_per_samp = 2 ;
- break ;
- }
-
- switch( audio_params->nchannels ) {
- default :
- case AL_MONO :
- fprintf( stderr, "%s: sound file %s is not in stereo\n",
- basename, filename ) ;
- return( NULL ) ;
-
- case AL_STEREO :
- samps_per_frame = 2 ;
- break ;
- }
-
- switch( audio_params->samprate ) {
- default :
- case AL_RATE_48000 :
- case AL_RATE_44100 :
- case AL_RATE_32000 :
- case AL_RATE_22050 :
- case AL_RATE_11025 :
- case AL_RATE_8000 :
- fprintf( stderr,
- "%s: sound file %s is not sampled at 16KHz\n",
- basename, filename ) ;
- return( NULL ) ;
- case AL_RATE_16000 :
- frames_per_sec = 16000 ;
- break ;
- }
-
- *size = comm_data->nsampframes * samps_per_frame * bytes_per_samp ;
-
- buf = (char *)malloc( *size ) ;
- lseek( fd, ssnd_data->file_position, SEEK_SET ) ;
- if( ( bytes_read = read( fd, buf, *size ) ) < *size ) {
- fprintf( stderr, "%s: short read on %s\n", basename, filename ) ;
- *size = bytes_read ;
- }
-
- *size /= samps_per_frame ;
-
- return( buf ) ;
- }
-
-
- #ifndef INV_AUDIO_A2
- #define INV_AUDIO_A2 3 /* HAL2 Audio Module for Indigo 2 */
- #endif
-
- static int check_for_audio_hw( void ) {
- int st = 0;
- inventory_t *base;
- inventory_t *inv;
-
-
- inv = base = getinvent() ;
- while (inv != NULL) {
-
- #ifdef OLD_STYLE_INVENT
- if (inv->class == INV_AUDIO && (inv->type == INV_AUDIO_HDSP
- || inv->type == INV_AUDIO_A2)) {
- st = 1;
- }
- #else
- if (inv->inv_class == INV_AUDIO && (inv->inv_type == INV_AUDIO_HDSP
- || inv->inv_type == INV_AUDIO_A2)) {
- st = 1;
- }
- #endif
- inv = getinvent() ;
- }
-
- if (base) {
- endinvent();
- }
-
- return( st ) ;
- }
-
-
-
- int volume_change(int direction) {
-
- get_gain();
- if( direction == 1 ) {
- if( gain_index <
- sizeof( gain_settings ) / sizeof( gain_settings[0] ) - 1 ) {
- gain_index++ ;
- }
- } else {
- if( gain_index > 0 ) {
- gain_index-- ;
- }
- }
- curr_left_gain = curr_right_gain = gain_settings[gain_index] ;
-
- set_gain( 1., 1. ) ;
-
- return( gain_index ) ;
- }
-
-
-
- static void set_gain_index(unsigned long gain) {
- int i ;
- long min = 256 ;
- long diff ;
-
- for (i = 0; i < sizeof(gain_settings) / sizeof(gain_settings[0]); i++ ) {
- diff = gain - gain_settings[i] ;
- if( diff < 0 )
- diff = -diff ;
- if( diff < min ) {
- min = diff ;
- gain_index = i ;
- }
- }
- }
-
-
-
- static void init_pan_data( int sound ) {
- int i;
- int size;
- short *s;
-
- size = sound_size[sound]-1;
- s = sound_data[sound]+1;
- for( i = 0 ; i < size; i += 2 ) {
- *(s+i) /= 2;
- }
- }
-